fn main() {
    let s1 = String::from("hello");

    // 指针属于借用，"hello"的归属没有变化。
    let mut l = cacl_len_by_ref(&s1);
    println!("The length is: {}", l);

    l = calc_len(s1);
    println!("The length is: {}", l);

    // 函数调用带走变量的归属
    // 将提示 value borrowed
    // rustc 很友好地提示，变量在calc_len时被move走了未归还。
    // println!("String: {}", s1);
    /*
     * note
     * rust通过内存只能有一个归属变量，限制了它不会像其他语言一样到处移动。
     * 这样当超出作用域时，它就会被自动释放了，归属无效。
     * 另外，这对于数据来说，非常有效果，不会有两个变量指向同一个地址，
     * 也就不会有对内存的不受控写了。
     *
     */

    // 实验整数
    // 为什么整数被move之后，仍然可以用？
    // 因为i32实现了Copy trait，传递时，其实传递的是i的副本。
    // 通过{:p}打印出本来的地址和传入函数后的地址是不同的，可以印证。
    //
    // 理解：string这种在堆上分配的空间，其复制成本较高，所以默认是不复制的。
    // 而i32就不一样了，更多情况下复制才是使用者的本意。
    let i : i32 = 1;
    inc(i);
    println!("After borrowed: {}, addr: {:p}", i, &i);
}

fn inc(i: i32) {
    println!("After increment: {}, addr: {:p}", i+1, &i);
}

fn cacl_len_by_ref(s: &String) -> usize {
    s.len()
}

fn calc_len(s: String) -> usize {
    s.len()
}
